<?php
/*
 * @Descripttion: 框架缓存类，直接利用数组保存在内存中，缓存数据的结构如下：
 *      cache => [
    *      'KEY' => [
    *                      'expire' => ...,    // 缓存有效期，设置缓存时的时间戳 + 有效期
    *                      'name' => VAL      // 保存的值
    *      ],
    *      ...
 *      ]
 * @version:
 * @Author: ewgof
 * @Date: 2020-09-01 11:30:11
 * @LastEditors: ewgof
 * @LastEditTime: 2020-10-25 17:09:34
 */
namespace cw;

use cw\interfaces\CacheInterface;

class MemoryCache extends Base implements CacheInterface
{
    protected $cache = [];
    protected $t = 0;
    protected $cache_prefix = '';  // 缓存键名前缀

    public function __construct()
    {
        global $cache;
        $this->cache = &$cache;
        $this->t = time();
        if (!empty(config('cache.prefix'))) {
            $this->cache_prefix = config('cache.prefix');
        } else {
            $this->cache_prefix = 'cw_cache:';
        }
    }


    public function get(String $name)
    {
        if (empty($name)) {
            return false;
        }
        if (isset($this->cache[$this->cache_prefix . $name])) {
            $data = $this->cache[$this->cache_prefix . $name];
            if ($data['expire'] == 0 || $data['expire'] >= $this->t) {
                $val = $data[$name];
            } else {
                $val = false;
                unset($this->cache[$this->cache_prefix . $name]);
            }
        } else {
            $val = false;
        }
        return $val;
    }


    public function set(String $name, $val, $expire = null)
    {
        if (empty($name)) {
            return false;
        }
        if ($expire === null) {
            $exp = config('cache.expire');
            $expire = $exp == 0 ? $exp : $exp + $this->t;
        } else {
            $expire += $this->t;
        }
        $this->cache[$this->cache_prefix . $name] = [$name => $val, 'expire' => $expire];
        return true;
    }

    /**
     * @name: inc
     * @msg: 缓存值自增
     * @param string $name 缓存键名
     * @param integer $step 自增步长，默认为1
     * @return boolean
     */
    public function inc(String $name, $step = 1)
    {
        if (empty($name)) {
            return false;
        }
        $expire = $this->cache[$this->cache_prefix . $name]['expire'];
        if ($expire == 0 || $expire >= $this->t) {
            $val = $this->cache[$this->cache_prefix . $name][$name];
            if (!\is_numeric($val)) {
                return false;
            }
            $this->cache[$this->cache_prefix . $name][$name] = $val + $step;
            return true;
        } else {
            return false;
        }
    }


    /**
     * @name: dec
     * @msg: 缓存值自减
     * @param string $name 缓存键名
     * @param integer $step 自减步长，默认为1
     * @return boolean
     */
    public function dec(String $name, $step = 1)
    {
        if (empty($name)) {
            return false;
        }
        $expire = $this->cache[$this->cache_prefix . $name]['expire'];
        if ($expire == 0 || $expire >= $this->t) {
            $val = $this->cache[$this->cache_prefix . $name][$name];
            if (!\is_numeric($val)) {
                return false;
            }
            $this->cache[$this->cache_prefix . $name][$name] = $val - $step;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @name: delete
     * @msg: 删除缓存值
     * @param string $name 缓存键名
     * @return boolean
     */
    public function delete(String $name)
    {
        unset($this->cache[$this->cache_prefix . $name]);
        return true;
    }


    /**
     * @name: pull
     * @msg: 获取并删除缓存值
     * @param string $name 缓存键名
     * @return mixed
     */
    public function pull(String $name)
    {
        if (empty($name)) {
            return false;
        }

        $expire = $this->cache[$this->cache_prefix . $name]['expire'];
        if ($expire == 0 || $expire >= $this->t) {
            $val = $this->cache[$this->cache_prefix . $name][$name];
            unset($this->cache[$this->cache_prefix . $name]);
            return $val;
        } else {
            return false;
        }
    }


    /**
     * @name: clean
     * @msg: 清除当前用户的全部缓存值
     * @param void
     * @return boolean
     */
    public function clean()
    {
        unset($this->cache);
        return true;
    }


    /**
     * @name: has
     * @msg: 判断缓存值是否存在
     * @param string $name 缓存键名
     * @return boolean
     */
    public function has(String $name)
    {
        if (empty($name)) {
            return false;
        }
        return isset($this->cache[$this->cache_prefix . $name]);
    }
}
